﻿using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using GTI = Gadgeteer.SocketInterfaces;

namespace Gadgeteer.Modules.GHIElectronics
{
    // -- CHANGE FOR MICRO FRAMEWORK 4.2 --
    // If you want to use Serial, SPI, or DaisyLink (which includes GTI.SoftwareI2CBus), you must do a few more steps
    // since these have been moved to separate assemblies for NETMF 4.2 (to reduce the minimum memory footprint of Gadgeteer)
    // 1) add a reference to the assembly (named Gadgeteer.[interfacename])
    // 2) in GadgeteerHardware.xml, uncomment the lines under <Assemblies> so that end user apps using this module also add a reference.

    /// <summary>
    /// A RS232 module for Microsoft .NET Gadgeteer
    /// </summary>
    public class RS232 : GTM.Module
    {
        /// <summary>
        /// The serial port used to send and receive data
        /// </summary>
        public GT.SocketInterfaces.Serial serialPort;
        private Socket socket;

        // Note: A constructor summary is auto-generated by the doc builder.
        /// <summary></summary>
        /// <param name="socketNumber">The socket that this module is plugged in to.</param>
        public RS232(int socketNumber)
        {
            socket = Socket.GetSocket(socketNumber, true, this, null);

            char[] types = new char[] { 'U', 'K' };

            socket.EnsureTypeIsSupported(types, this);

            //// This creates an GTI.InterruptInput interface. The interfaces under the GTI namespace provide easy ways to build common modules.
            //// This also generates user-friendly error messages automatically, e.g. if the user chooses a socket incompatible with an interrupt input.
            //this.input = GTI.InterruptInputFactory.Create(socket, GT.Socket.Pin.Three, GTI.GlitchFilterMode.On, GTI.ResistorMode.PullUp, GTI.InterruptMode.RisingAndFallingEdge, this);

            //// This registers a handler for the interrupt event of the interrupt input (which is below)
            //this.input.Interrupt += (this._input_Interrupt);
        }

        /// <summary>
        /// Initializes the serial port to the passed in parameters. If no parameters are passed, the defaults are used.
        /// </summary>
        /// <param name="baudRate">The baud rate for the serail port. Defaulted to 38400.</param>
        /// <param name="parity">Specifies the parity bit for the serial port. Defaulted to none.</param>
        /// <param name="stopBits">Specifies the number of stop bits used on the serial port. Defaulted to one.</param>
        /// <param name="dataBits">The number of data bits. Defaulted to 8.</param>
        /// <param name="flowControl">Specifies if the serial port should use flow control. Defaulted to not use.</param>
        public void Initialize(int baudRate = 38400, GTI.SerialParity parity = GTI.SerialParity.None,
            GTI.SerialStopBits stopBits = GTI.SerialStopBits.One, int dataBits = 8, GTI.HardwareFlowControl flowControl = GTI.HardwareFlowControl.NotRequired)
        {
            // Set up serial port.
            serialPort = GTI.SerialFactory.Create(socket, baudRate, parity, stopBits, dataBits, flowControl, this);

            serialPort.Open();

            // Subscribe to events.
            //serialPort.DataReceived += GTI.SerialFactory.Create.DataReceivedEventHandler(serialPort_DataReceived);
            //serialPort.LineReceived += GTI.SerialFactory.Create.LineReceivedEventHandler(serialPort_LineReceived);
        }

        //void serialPort_LineReceived(GTI.Serial sender, string line)
        //{
        //    throw new NotImplementedException();
        //}

        //void serialPort_DataReceived(GTI.Serial sender, System.IO.Ports.SerialData data)
        //{
        //    throw new NotImplementedException();
        //    serialPort.
        //}

        //private void _input_Interrupt(GTI.InterruptInput input, bool value)
        //{
        //    this.OnRS232Event(this, value ? RS232State.Low : RS232State.High);
        //}

        //private GTI.InterruptInput input;

        ///// <summary>
        ///// Gets a value that indicates whether the state of this RS232 is high.
        ///// </summary>
        //public bool IsHigh
        //{
        //    get
        //    {
        //        return this.input.Read();
        //    }
        //}

        ///// <summary>
        ///// Represents the state of the <see cref="RS232"/> object.
        ///// </summary>
        //public enum RS232State
        //{
        //    /// <summary>
        //    /// The state of RS232 is low.
        //    /// </summary>
        //    Low = 0,
        //    /// <summary>
        //    /// The state of RS232 is high.
        //    /// </summary>
        //    High = 1
        //}

        ///// <summary>
        ///// Represents the delegate that is used to handle the <see cref="RS232High"/>
        ///// and <see cref="RS232Low"/> events.
        ///// </summary>
        ///// <param name="sender">The <see cref="RS232"/> object that raised the event.</param>
        ///// <param name="state">The state of the RS232</param>
        //public delegate void RS232EventHandler(RS232 sender, RS232State state);

        ///// <summary>
        ///// Raised when the state of <see cref="RS232"/> is high.
        ///// </summary>
        ///// <remarks>
        ///// Implement this event handler and the <see cref="RS232Low"/> event handler
        ///// when you want to provide an action associated with RS232 activity.
        ///// The state of the RS232 is passed to the <see cref="RS232EventHandler"/> delegate,
        ///// so you can use the same event handler for both RS232 states.
        ///// </remarks>
        //public event RS232EventHandler RS232High;

        ///// <summary>
        ///// Raised when the state of <see cref="RS232"/> is low.
        ///// </summary>
        ///// <remarks>
        ///// Implement this event handler and the <see cref="RS232High"/> event handler
        ///// when you want to provide an action associated with RS232 activity.
        ///// Since the state of the RS232 is passed to the <see cref="RS232EventHandler"/> delegate,
        ///// you can use the same event handler for both RS232 states.
        ///// </remarks>
        //public event RS232EventHandler RS232Low;

        //private RS232EventHandler onRS232;

        ///// <summary>
        ///// Raises the <see cref="RS232High"/> or <see cref="RS232Low"/> event.
        ///// </summary>
        ///// <param name="sender">The <see cref="RS232"/> that raised the event.</param>
        ///// <param name="RS232State">The state of the RS232.</param>
        //protected virtual void OnRS232Event(RS232 sender, RS232State RS232State)
        //{
        //    if (this.onRS232 == null)
        //    {
        //        this.onRS232 = new RS232EventHandler(this.OnRS232Event);
        //    }

        //    if (Program.CheckAndInvoke((RS232State == RS232State.High ? this.RS232High : this.RS232Low), this.onRS232, sender, RS232State))
        //    {
        //        switch (RS232State)
        //        {
        //            case RS232State.High:
        //                this.RS232High(sender, RS232State);
        //                break;
        //            case RS232State.Low:
        //                this.RS232Low(sender, RS232State);
        //                break;
        //        }
        //    }
        //}

        #region Exposed Serial Members

        #endregion
    }
}